package utilities;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import model.EdgeTransitionSystem;
import model.NodeTransitionSystem;
import model.NodeUnfoldingTransitionSystem;
import model.TransitionSystem;
import model.UnfoldingTransitionSystem;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/** Class for XML writing of a given graph in a .jff file for JFLAP
 * @author DarkoLaptop2
 *
 */
public class XMLWriter {

	/** Method for creating a XML document from a given graph without variables
	 * @param graph - the graph that will be converted to XML document
	 * @return XML document for .jff file
	 * @throws ParserConfigurationException
	 */
	public static Document createXMLDocumentForSupervisor(TransitionSystem graph)
			throws ParserConfigurationException {
		DocumentBuilderFactory docFactory = DocumentBuilderFactory
				.newInstance();
		DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
		Document doc = docBuilder.newDocument();
		Element root = doc.createElement("structure");
		doc.appendChild(root);
		Element typeEl = doc.createElement("type");
		typeEl.appendChild(doc.createTextNode("fa"));
		root.appendChild(typeEl);
		Element automationEl = doc.createElement("automaton");
		root.appendChild(automationEl);
		for (NodeTransitionSystem node : graph.getAllNodes()) {
			if(node==null)
				continue;
			Element stateEl = doc.createElement("state");
			Attr attrId = doc.createAttribute("id");
			attrId.setValue(node.getIndex() + "");
			Attr attrName = doc.createAttribute("name");
			attrName.setValue(node.getName());
			stateEl.setAttributeNode(attrId);
			stateEl.setAttributeNode(attrName);
			if (graph.getInitialNode().getIndex() == node.getIndex()) {
				Element initialEl=doc.createElement("initial");
				stateEl.appendChild(initialEl);
			}
//			if(graph instanceof UnfoldingTransitionSystem){
//				NodeUnfoldingTransitionSystem nodeUn=(NodeUnfoldingTransitionSystem) node;
//				Element labelEl=doc.createElement("label");
//				labelEl.appendChild(doc.createTextNode(nodeUn.getVariablesTable()+""));
//				stateEl.appendChild(labelEl);
//			}
			automationEl.appendChild(stateEl);
		}
		for (EdgeTransitionSystem transition: graph.getAllTransitionsList()){
			Element transitionEl = doc.createElement("transition");
			Element elFrom = doc.createElement("from");
			elFrom.appendChild(doc.createTextNode(transition.getFromNode().getIndex()+""));
			transitionEl.appendChild(elFrom);
			Element elTo = doc.createElement("to");
			elTo.appendChild(doc.createTextNode(transition.getToNode().getIndex()+""));
			transitionEl.appendChild(elTo);
			Element elRead = doc.createElement("read");
			elRead.appendChild(doc.createTextNode(transition.getTransitionName()));
			transitionEl.appendChild(elRead);
			automationEl.appendChild(transitionEl);
		}
		return doc;
	}
	
	/** Method for creating a XML file for a given graph without variables and a given filename and path of the XML file
	 * @param graph - the graph that will be written to XML file
	 * @param fileName - the path and name of the XML file
	 * @throws ParserConfigurationException 
	 * @throws TransformerException
	 */
	public static void writeXMLDocumentForSupervisor(TransitionSystem graph, String fileName) throws ParserConfigurationException, TransformerException{
		Document docXML=createXMLDocumentForSupervisor(graph);
		TransformerFactory transformerFactory = TransformerFactory
				.newInstance();
		Transformer transformer = transformerFactory.newTransformer();
		DOMSource source = new DOMSource(docXML);
		StreamResult result=new StreamResult(new File(fileName));
		transformer.transform(source,result);
	}
}
